﻿#include "QueueBuffer.h"
#include <QByteArray>
#include <QMutex>
#include <QDebug>
#include <QThread>

// TODO
/* 设计为可拓展读写的 */

QueueBuffer::QueueBuffer(qint64 size):m_size(size),m_wpos(0),m_rpos(0)
{
    m_buffer = new QByteArray(m_size,0);
    m_remain = m_size;
    Q_ASSERT(m_buffer);
    m_mutex = new QMutex;
}

QueueBuffer::~QueueBuffer(){
    delete m_buffer;
    delete m_mutex;
}

bool QueueBuffer::open(OpenMode mode){
    return QIODevice::open(mode | QIODevice::Unbuffered);//不使用缓冲
}

/****************************************************************************
 ** 由QAudioOutput读取，顺序是写，写，写，写，...，读，写，写，写，...，读
 ****************************************************************************/

qint64 QueueBuffer::readData(char *data, qint64 maxlen) {
    QMutexLocker loker(m_mutex);
    if(maxlen > m_size || (m_size - m_remain) < maxlen){
        qDebug() << "read warning:" << m_size << maxlen;
        return 0;
    }

    if(m_rpos + maxlen < m_size){
        memcpy(data,m_buffer->data() + m_rpos,maxlen);
        m_rpos += maxlen;
        m_remain += maxlen;
    }else{
        // 分段式
        int remain = m_size - m_rpos;
        memcpy(data,m_buffer->data() + m_rpos,remain);
        m_rpos = (m_rpos + remain) % m_size;
        memcpy(data + remain,m_buffer->data() + m_rpos,maxlen - remain);
        m_rpos += maxlen -remain;
        m_remain += maxlen;
    }

    return maxlen;
}

/****************************************************************************
 ** 由QAudioInput写入，顺序是写，写，写，写，...，读，写，写，写，...，读
 ** 如果想保存原始数据，可以在这里做处理
 ****************************************************************************/

qint64 QueueBuffer::writeData(const char *data, qint64 len){
    QMutexLocker loker(m_mutex);
    if(len > m_size || m_remain < len){
        qDebug() << "write warning" << m_size << len;
        return 0;
    }

    if(m_wpos + len < m_size){
        memcpy(m_buffer->data() + m_wpos,data,len);
        m_wpos = m_wpos + len;
        m_remain -= len;
    }else{
        // 分段式
        int remain = m_size - m_wpos;
        memcpy(m_buffer->data() + m_wpos,data,remain);
        m_wpos = (m_wpos + remain) % m_size;
        memcpy(m_buffer->data() + m_wpos,data + remain,len - remain);
        m_wpos += (len -remain);
        m_remain -= len;
    }

    return len;
}
